<template>
	<div>
		<div v-show="showContainer" class="face-capture" id="face-capture">
			<video ref="refVideo" id="video" autoplay width="420" height="300"></video>
			<div class="control-container face-capture">
				<h2 class="title">{{scanTip}}</h2>
				<canvas ref="refCanvas" :width="screenSize.width" :height="screenSize.height" :style="{opacity: 0}"></canvas>
			</div>
			<!-- <div class="rect" v-for="item in profile" :style="{ width: item.width + 'px', height: item.height + 'px', left: item.left + 'px', top: item.top + 'px'}"></div> -->
		</div>
		<img :src="imgUrl" v-show="!showContainer" id="photo" />
		<el-button @click="scratchMore()" v-show="!showContainer">重新捕捉</el-button>
	</div>
</template>

<script>
	require('tracking/build/tracking-min.js')
	require('tracking/build/data/face-min.js')
	require('tracking/build/data/mouth-min.js')
	require('tracking/examples/assets/stats.min.js')
	import * as faceApi from '../../api/faceApi.js'

	export default {
		name: 'testTracking',
		data() {
			return {
				screenSize: {
					width: 420,
					height: 300
				},
				URL: null,
				streamIns: null, // 视频流
				showContainer: true, // 显示
				tracker: null,
				tipFlag: false, // 提示用户已经检测到
				flag: false, // 判断是否已经拍照
				context: null, // canvas上下文
				// profile: [], // 轮廓
				removePhotoID: null, // 停止转换图片
				scanTip: '人脸识别中...', // 提示文字
				imgUrl: '' // base64格式图片
			}
		},
		mounted() {
			this.playVideo()
		},
		methods: {
			scratchMore() {
				this.showContainer = true
				this.tipFlag = false
				this.playVideo()
			},
			// 访问用户媒体设备
			getUserMedia(constrains, success, error) {
				if (navigator.mediaDevices.getUserMedia) {
					//最新标准API
					navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error);
				} else if (navigator.webkitGetUserMedia) {
					//webkit内核浏览器
					navigator.webkitGetUserMedia(constrains).then(success).catch(error);
				} else if (navigator.mozGetUserMedia) {
					//Firefox浏览器
					navagator.mozGetUserMedia(constrains).then(success).catch(error);
				} else if (navigator.getUserMedia) {
					//旧版API
					navigator.getUserMedia(constrains).then(success).catch(error);
				} else {
					this.scanTip = "你的浏览器不支持访问用户媒体设备"
				}
			},
			success(stream) {
				this.streamIns = stream
				// webkit内核浏览器
				this.URL = window.URL || window.webkitURL
				if ("srcObject" in this.$refs.refVideo) {
					this.$refs.refVideo.srcObject = stream
				} else {
					this.$refs.refVideo.src = this.URL.createObjectURL(stream)
				}
				this.$refs.refVideo.onloadedmetadata = e => {
					this.$refs.refVideo.play()
					this.initTracker()
				}
			},
			error(e) {
				this.scanTip = "访问用户媒体失败" + e.name + "," + e.message
			},
			playVideo() {
				this.getUserMedia({
					video: {
						width: 420,
						height: 300,
						facingMode: "user"
					} /* 前置优先 */
				}, this.success, this.error)
			},
			// 人脸捕捉
			initTracker() {
				this.context = this.$refs.refCanvas.getContext("2d") // 画布
				this.tracker = new tracking.ObjectTracker(['face']) // tracker实例
				this.tracker.setStepSize(2) // 设置步长
				this.tracker.setEdgesDensity(0.1);
				this.tracker.on('track', this.handleTracked) // 绑定监听方法
				try {
					tracking.track('#video', this.tracker) // 开始追踪
				} catch (e) {
					this.scanTip = "访问用户媒体失败，请重试"
				}
			},
			// 追踪事件
			handleTracked(e) {
				if (e.data.length === 0) {
					this.scanTip = '未检测到人脸'
				} else {
					if (!this.tipFlag) {
						this.scanTip = '检测成功，正在拍照，请保持不动2秒'
					}
					// 1秒后拍照，仅拍一次
					if (!this.flag) {
						this.scanTip = '拍照中...'
						this.flag = true
						this.removePhotoID = setTimeout(() => {
							this.tackPhoto()
							this.tipFlag = true
						}, 1000)
					}
				}
			},
			tackPhoto() {
				this.context.drawImage(this.$refs.refVideo, 0, 0, this.screenSize.width, this.screenSize.height)
				// 保存为base64格式
				this.imgUrl = this.saveAsPNG(this.$refs.refCanvas)
				/** 拿到base64格式图片之后就可以在this.compare方法中去调用后端接口比较了，也可以调用getBlobBydataURI方法转化成文件再去比较
				 * 我们项目里有一个设置个人头像的地方，先保存一下用户的图片，然后去拿这个图片的地址和当前拍照图片给后端接口去比较。
				 * */
				this.compare(this.imgUrl)
				this.close()
			},
			// Base64转文件
			getBlobBydataURI(dataURI, type) {
				var binary = window.atob(dataURI.split(',')[1]);
				var array = [];
				for (var i = 0; i < binary.length; i++) {
					array.push(binary.charCodeAt(i));
				}
				return new Blob([new Uint8Array(array)], {
					type: type
				});
			},
			compare(url) {
				let blob = this.getBlobBydataURI(url, 'image/png')
				let imgSrc = url.split(';')[1].replace("base64,", "")
				let formData = new FormData()
				formData.append("file", blob, "file_" + Date.parse(new Date()) + ".png")
				// TODO 得到文件后进行人脸识别
				const config = {
					headers: {
						'Content-Type': 'multipart/form-data'
					}
				}
				faceApi.faceSearch(formData, config).then(res => {
					console.log(res.data)
				})
			},
			// 保存为png,base64格式图片
			saveAsPNG(c) {
				return c.toDataURL('image/png', 0.3)
			},
			// 关闭并清理资源
			close() {
				this.flag = false
				this.tipFlag = false
				this.showFailPop = false
				this.showContainer = false
				this.tracker && this.tracker.removeListener('track', this.handleTracked)
				this.tracker = null
				this.context = null
				this.profile = []
				this.scanTip = '人脸识别中...'
				clearTimeout(this.removePhotoID)
				if (this.streamIns) {
					this.streamIns.enabled = false
					this.streamIns.getTracks()[0].stop()
					this.streamIns.getVideoTracks()[0].stop()
				}
				this.streamIns = null
			}
		}
	}
</script>

<style scoped>
	.face-capture {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.face-capture video,
	.face-capture canvas {
		position: fixed;
		top: 0;
		bottom: 0;
		left: 500px;
		right: 0;
		width: 420;
		height: 300;
		object-fit: cover;
		z-index: 2;
		background-repeat: no-repeat;
		background-size: 100% 100%;
	}

	.face-capture canvas {
		z-index: 2;
	}

	.face-capture .rect {
		border: 2px solid #0aeb08;
		position: fixed;
		z-index: 3;
	}

	.face-capture .control-container {
		margin-top: 10rem;
		position: relative;
		width: 100%;
		height: 100%;
		object-fit: cover;
		z-index: 4;
		background-repeat: no-repeat;
		background-size: 100% 100%;
	}

	.face-capture .title {
		/* text-align: center; */
		color: white;
		/* margin: 1.6rem auto; */
		font-size: 18px;
	}

	.face-capture .close {
		width: 0.8rem;
		height: 0.8rem;
	}

	#photo {
		position: fixed;
		top: 0;
		bottom: 0;
		left: 500px;
		right: 0;
		width: 420px;
		height: 300px;

	}
</style>
